﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using Microsoft.Office.Core;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;

namespace DataFactory
{
	public static class LinkedRangeSerializer
	{
		private static string _partId;

		public static List<T> DeSerializeAll<T>(Excel.Workbook wb, string baseName) {
			
			IEnumerable<CustomXMLPart> xmlParts = GetAllXMLParts(wb, baseName);
		 	List<T> objects = new List<T>();

            if (xmlParts != null) {
            	foreach(var customXmlPart in xmlParts) {
            		string xmlString = customXmlPart.XML;
            		objects.Add(DeserializeObject<T>(xmlString));
            	}
            }

           return objects;
		}

		public static void SerializeOne(Excel.Workbook wb, object o) {
			
			string xmlString = SerializeObject(o);

            if (_partId == null)
                _partId = AddXmlPart(wb, xmlString);
            else
            {
                wb.CustomXMLParts.SelectByID(_partId).Delete();
                _partId = AddXmlPart(wb, xmlString);
            }
		}

		private static string AddXmlPart(Excel.Workbook wb, string xmlString)
        {
            CustomXMLPart xmlPart = wb.CustomXMLParts.Add(xmlString);

            return xmlPart.Id;
        }

		private static CustomXMLPart GetXMLPart(Excel.Workbook wb, string baseName) { 
			return wb.CustomXMLParts.Cast<CustomXMLPart>().FirstOrDefault(part => part.DocumentElement.BaseName == baseName); 
		}

    	private static IEnumerable<CustomXMLPart> GetAllXMLParts(Excel.Workbook wb, string baseName) {
			return wb.CustomXMLParts.Cast<CustomXMLPart>().Where(part => part.DocumentElement.BaseName == baseName).ToList();
		}


		public static String SerializeObject(Object o)
        {   
            using (MemoryStream stream = new MemoryStream())
            {
                XmlSerializer serializer = new XmlSerializer(o.GetType());

                serializer.Serialize(stream, o);

                return System.Text.Encoding.UTF8.GetString(stream.ToArray());
            }
        }

		public static T DeserializeObject<T>(string xmlString)
        {
            Byte[] bytes = System.Text.Encoding.UTF8.GetBytes(xmlString);

            using (MemoryStream stream = new MemoryStream(bytes))
            {
                XmlSerializer deserializer = new XmlSerializer(typeof(T));

                return (T)deserializer.Deserialize(stream);
            }
        }

		public static void SerializeToWorkbook(Excel.Workbook wb, object o)
        {   
            string xmlString = SerializeObject(o);

            if (_partId == null)
                _partId = AddXmlPart(wb, xmlString);
            else
            {
                wb.CustomXMLParts.SelectByID(_partId).Delete();
                _partId = AddXmlPart(wb, xmlString);
            }
        }
	}
}
